[BITS 32]

KERNEL_STACK_SIZE			equ 0x4000
KERNEL_ARGS_SIGNATURE		equ 0x1EA7BEEF
MULTIBOOT_ARGS_SIGNATURE	equ 0x2BADB002

extern MULTIBOOT_PREPARE_ARGS
extern KERNEL_CPP_INITIALIZE
extern KERNEL_CPP_SHUTDOWN
extern KERNEL_CPP_RUN
extern code
extern bss
extern end
extern ctors
extern ctors_end
extern dtors
extern dtors_end
extern _Kernel_Start
global Kernel_Entry
global _Kernel_Stack
global _Kernel_StackSize
global _Kernel_BootSignature;
global _Kernel_BootArgs;


;-------------------------------------------------------------------------------
; Entry Code
;-------------------------------------------------------------------------------
section .entry
align 4
Kernel_Entry:
	cli

	; setup stack and copy stack location to global variabl
	mov		esp, Stack + KERNEL_STACK_SIZE
	mov		[_Kernel_Stack], esp

	; load gdt
	lgdt	[GDT_Pointer]

	; setup segments
	mov		ecx, 0x10
	mov		ds, cx
	mov		es, cx
	mov		fs, cx
	mov		gs, cx
	mov		ss, cx

	mov     [_Kernel_BootSignature], dword 0
	mov     [_Kernel_BootArgs], dword 0

    ; check for our bootloader args
    cmp		eax, dword KERNEL_ARGS_SIGNATURE
	je		.save_boot_args

    ; check for multiboot compliant bootloader args
	cmp		eax, dword MULTIBOOT_ARGS_SIGNATURE
	je		.save_boot_args

	jmp		.execute_ctors

 .save_boot_args:
	mov     [_Kernel_BootSignature], eax
	mov     [_Kernel_BootArgs], ebx

 .execute_ctors:
	mov		ebx, ctors
	jmp		.check_ctor
 .execute_ctor:
 	call	[ebx]
 	add		ebx, 4
 .check_ctor:
 	cmp		ebx, ctors_end
 	jne		.execute_ctor

	call	_Kernel_Start

 .execute_dtors:
	mov		ebx, dtors
	jmp		.check_dtor
 .execute_dtor:
 	call	[ebx]
 	add		ebx, 4
 .check_dtor:
 	cmp		ebx, dtors_end
 	jne		.execute_dtor

.halt:
	cli
	hlt
	jmp		.halt


;-------------------------------------------------------------------------------
; Variables
;-------------------------------------------------------------------------------
section .data

_Kernel_Stack:
	dd		0

_Kernel_StackSize:
	dd		KERNEL_STACK_SIZE

_Kernel_BootSignature:
    dd      0

_Kernel_BootArgs:
	dd		0


GDT:
	; NULL descriptor
	dw		0
	dw		0
	db		0
	db		0
	db		0
	db		0

LOADER_CODE_SEGMENT equ $ - GDT
	dw		0xFFFF
	dw		0
	db		0
	db		10011010b
	db		11001111b
	db		0

LOADER_DATA_SEGMENT equ $ - GDT
	dw		0xFFFF
	dw		0
	db		0
	db		10010010b
	db		11001111b
	db		0

LOADER_CODE_SEGMENT64 equ $ - GDT
	dw		0xFFFF
	dw		0
	db		0
	db		10011010b
	db		10101111b
	db		0


GDT_Pointer:
	dw		$ - GDT - 1
	dd		GDT


;-------------------------------------------------------------------------------
; Kernel Stack
;-------------------------------------------------------------------------------
section .bss
Stack:
	resb	KERNEL_STACK_SIZE

